package visitors;

import manager.AbstractVisitor;
import manager.IAnalizadorSintactico;
import manager.IVisitor;
import model.*;

public class LoggingVisitor extends AbstractVisitor { 
	
	//Singleton
	private static IVisitor instance = new LoggingVisitor();
	private LoggingVisitor(){}
	public static IVisitor getInstance() { return instance; }
	
/*    Loguea la gramatica
<PROGRAMA> -> globales <HEADER> fin-globales;  BLOQUE EOF 

<BLOQUE> -> procedimiento IDENTIFICADOR(<BLOQUE_PARAM>); <HEADER> comenzar <SENTENCIA> END-PROC       ; <BLOQUE>|
			funcion  IDENTIFICADOR(<BLOQUE_PARAM>): <TIPO>; <HEADER> comenzar <SENTENCIA>  fin-proc; <BLOQUE>|
		 
<HEADER> -> const IDENTIFICADOR : <TIPO_C> ;<HEADER>  | 
			var <VAR> ; <HEADER> |
			adelante
			LAMBDA	
<TIPO_C> -> NATURAL = NUMERO_NAT					|
            NATURAL = NUMERO_NAT , IDENTIFICADOR : <TIPO_C> 	|
            INTEGER = NUMERO     , IDENTIFICADOR : <TIPO_C>	|
            INTEGER = NUMERO

<VAR> -> IDENTIFICADOR , <VAR> 			|
         IDENTIFICADOR : <TIPO>;			|
         IDENTIFICADOR [ NUMERO     ] , <VAR>	|
         IDENTIFICADOR [ NUMERO_NAT ] , <VAR>	|
         IDENTIFICADOR [ NUMERO     ] : <TIPO>; 	|
         IDENTIFICADOR [ NUMERO_NAT ] : <TIPO>;

<TIPO> -> INTEGER | NATURAL

<BLOQUEVARPARAM> -> PORREFERENCIA IDENTIFICADOR : <TIPO> |
                  PORVALOR 		IDENTIFICADOR : <TIPO> |
								IDENTIFICADOR : <TIPO> |
                  PORREFERENCIA IDENTIFICADOR : <TIPO>, <BLOQUEVARPARAM> |
                  PORVALOR 		IDENTIFICADOR : <TIPO>, <BLOQUEVARPARAM> |
								IDENTIFICADOR : <TIPO>, <BLOQUEVARPARAM>

<SENTENCIA>-> IDENTIFICADOR           := <EXP > 				    		; <SENTENCIA>	|
			  IDENTIFICADOR [ <EXP> ] := <EX P> 				    		; <SENTENCIA>	|
		      IDENTIFICADOR ( <FACTOR_1> )      				    		; <SENTENCIA>	|
		      SI <CONDICION> ENTONCES <SENTENCIA> <SINO> <SENTENCIA> FIN-SI ; <SENTENCIA> 	|
		      SI <CONDICION> ENTONCES <SENTENCIA> FIN-SI   				 	; <SENTENCIA> 	|
		      MIENTRAS 	<CONDICION> HACER   <SENTENCIA> FIN-MIENTRAS		; <SENTENCIA> 	|
		      MOSTRARLN <MOSTRAR_ELEM> 					    				; <SENTENCIA>	|
		      MOSTRAR   <MOSTRAR_ELEM>					    				; <SENTENCIA> 	|
		      LEER   IDENTIFICADOR						    				; <SENTENCIA> 	|
																			; <SENTENCIA> 	|
		      LAMBDA

 <CONDICION> -> 	IMPAR  (<EXP>)	|
					PAR    (<EXP>) 	|
					<EXP>  = <EXP>	|
					<EXP> >= <EXP>	|
					<EXP> <= <EXP>	|
					<EXP>  < <EXP>	|
					<EXP>  > <EXP>	|
					<EXP> <> <EXP>

<MOSTRAR_ELEM> -> CADENA |
				  CADENA, <MOSTRAR_ELEM> |
				  <EXP> , <MOSTRAR_ELEM> |
				  <EXP>    		

<EXP> -> <TERMINO>  ++ <EXP> |
         <TERMINO>   + <EXP> |
         <TERMINO>  -- <EXP> |
         <TERMINO>   - <EXP> |
         <TERMINO>

<TERMINO> -> <FACTOR>             			|
			 <FACTOR> 	       * <TERMINO> 	|
			 <FACTOR> 	      ** <TERMINO> 	|
			 <FACTOR> 	       / <TERMINO> 	|
			 <FACTOR>          // <TERMINO>	|
			 ANATURAL (<EXP>)    			|
			 ANATURAL (<EXP>)  * <TERMINO> 	|
			 ANATURAL (<EXP>) ** <TERMINO> 	|
			 ANATURAL (<EXP>)  / <TERMINO> 	|
			 ANATURAL (<EXP>) // <TERMINO> 	|
			 AINTEGER (<EXP>)             	|
			 AINTEGER (<EXP>)  * <TERMINO> 	|
			 AINTEGER (<EXP>)  / <TERMINO> 	|
			 AINTEGER (<EXP>) ** <TERMINO> 	|
			 AINTEGER (<EXP>) // <TERMINO>	

<FACTOR> ->	( <EXP> )   				| 
           	NUMERO     					|
           	NUMERO_NAT 					|
           	IDENTIFICADOR ( <FACTOR1> )	|
			IDENTIFICADOR [ <EXP> ]		|
			IDENTIFICADOR
		   
<FACTOR1> -> <EXP> , <FACTOR1>	|
      		 <EXP> 				|
             LAMBDA */
	
	protected void visit(AnalizadorSintactico nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer Programa:\n" +
			    "   <PROGRAMA> -> GLOBALES <HEADER> FIN-GLOBALES; BLOQUE EOF' ");
			break;
		}
	}
	
	protected void visit(BloqueVarParam nt) {
		
		switch (nt.getNroProduccion()) {

		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueVarParam:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<BLOQUE_VAR_PARAM> -> PORREFERENCIA IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>");
			break;
		
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<BLOQUE_VAR_PARAM> -> PORVALOR	IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>");
			break;
			
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<BLOQUE_VAR_PARAM> -> IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>");
			break;
		}
	}
	protected void visit(Condicion nt) {
	
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer Condicion:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<CONDICION> -> IMPAR(<EXP>)");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<CONDICION> -> PAR(<EXP>)");
			break;
			
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<CONDICION> -> <EXP> C1 <EXP>");
			break;
		//
		}
	}
	
	protected void visit(Expresion nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueExpresion:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<EXP> -> <TERMINO> <E1> <EXP> | <TERMINO>");
			break;

		}
	}
	
	protected void visit(Factor nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueFactor:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<FACTOR> -> ( <EXP> )");
			break;
		
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<FACTOR> -> NUMERO");
			break;
			
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<FACTOR> -> NUMERO_NAT");
			break;

		case IAnalizadorSintactico.PROD_CUARTA:
			nt.getErrorManager().debug( "<FACTOR> -> IDENTIFICADOR ( <FACTOR1> )");

		case IAnalizadorSintactico.PROD_QUINTA:
			nt.getErrorManager().debug( "<FACTOR> -> IDENTIFICADOR [ <EXP> ]");

		case IAnalizadorSintactico.PROD_SEXTA:
			nt.getErrorManager().debug( "<FACTOR> -> IDENTIFICADOR ");
		
			break;
		
		}
	}
	
	protected void visit(Header nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueHeader:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<HEADER> -> CONST IDENTIFICADOR : <TIPO_C> <HEADER>");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<HEADER> -> VAR <VAR>; <HEADER>");
			break;			
		}
	}
	
	protected void visit(Bloque nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueBloque:");
			break;

		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<BLOQUE> -> PROCEDIMIENTO IDENTIFICADOR ( <BLOQUE_VAR_PARAM> ) ;<HEADER> COMENZAR <SENTENCIA> END-PROC       ; <BLOQUE>|");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<BLOQUE> -> FUNCION  IDENTIFICADOR(<BLOQUE_VAR_PARAM>): <TIPO>;<HEADER> COMENZAR <SENTENCIA>  fin-proc; <BLOQUE>");
			break;			
		}
	}
	
protected void visit(Bloque1 nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueBloque1:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<<BLOQUE1> -> <HEADER> COMENZAR <SENTENCIA> <B'>");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<BLOQUE1> -> ADELANTE");
			break;			
		}
	}
	
	protected void visit(Sentencia nt) {
	
		switch (nt.getNroProduccion()) {		
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueSentencia:");
			break;
	
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<SENTENCIA> -> IDENTIFICADOR := <EXP>           ; <SENTENCIA>");
			break;
	
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<SENTENCIA> -> IDENTIFICADOR [ <EXP> ] := <EXP> ; <SENTENCIA>");
			break;
		
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<SENTENCIA> -> IDENTIFICADOR ( <FACTOR_1> )     ; <SENTENCIA>");
			break;
			
		case IAnalizadorSintactico.PROD_CUARTA:
			nt.getErrorManager().debug( "<SENTENCIA> -> SI <CONDICION> ENTONCES <SENTENCIA> <SINO> <SENTENCIA> FIN-SI ; <SENTENCIA>");
			break;
			
		case IAnalizadorSintactico.PROD_QUINTA:
			nt.getErrorManager().debug( "SI <CONDICION> ENTONCES <SENTENCIA> FIN-SI ; <SENTENCIA>");
			break;
			
		case IAnalizadorSintactico.PROD_SEXTA:
			nt.getErrorManager().debug( "<SENTENCIA> ->MIENTRAS <CONDICION> HACER <SENTENCIA> FIN-MIENTRAS; <SENTENCIA>");
			break;
			
		case IAnalizadorSintactico.PROD_SEPTIMA:
			nt.getErrorManager().debug( "<SENTENCIA> -> MOSTRARLN <MOSTRAR_ELEM> 	; <SENTENCIA>");
			break;			
			
		case IAnalizadorSintactico.PROD_OCTAVA:
			nt.getErrorManager().debug( "<SENTENCIA> -> MOSTRARLN <MOSTRAR_ELEM> ; <SENTENCIA>");
			break;
		
		case IAnalizadorSintactico.PROD_NOVENA:
			nt.getErrorManager().debug( "<SENTENCIA> -> LEER   IDENTIFICADOR	; <SENTENCIA>");
			break;
			
		case IAnalizadorSintactico.PROD_DECIMA:
			nt.getErrorManager().debug( "<SENTENCIA> -> ; <SENTENCIA> ");
			break;
			
		}
	}
	
	protected void visit(MostrarElem nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueMostrarElem:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<MOSTRARELEM> -> CADENA <MOSTRARELEM>");
			break;
		
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<MOSTRARELEM>> -> <EXP> <MOSTRARELEM>");
			break;
		}
	}
		
	protected void visit(Termino nt) {

		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueTermino:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<TERMINO> -> <FACTOR> <T'>");
			break;
		}
	}
	
	protected void visit(Tipo nt) {
		
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueTipo:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<TIPO> -> ENTERO ");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<TIPO> -> NATURAL");
			break;			
		}
	}
	
	protected void visit(TipoC nt) {
	
		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueTipoC:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<TIPO_C> -> NATURAL = NUMERO_NAT");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<TIPO_C> -> NATURAL = NUMERO_NAT , IDENTIFICADOR : <TIPO_C>");
			break;
			
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<TIPO_C> -> ENTERO = NUMERO     , IDENTIFICADOR : <TIPO_C>");
			break;
			
		case IAnalizadorSintactico.PROD_CUARTA:
			nt.getErrorManager().debug( "<TIPO_C> -> ENTERO = NUMERO");
			break;
		}	
	}
	
	protected void visit(Var nt) {

		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueVar:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<VAR> -> IDENTIFICADOR , <VAR>");
			break;
			
		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<VAR> -> IDENTIFICADOR : <TIPO>;");
			break;
			
		case IAnalizadorSintactico.PROD_TERCERA:
			nt.getErrorManager().debug( "<VAR> -> IDENTIFICADOR [ NUMERO ]");
			break;
			
		case IAnalizadorSintactico.PROD_CUARTA:
			nt.getErrorManager().debug( "IDENTIFICADOR [ NUMERO_NAT ]");
			break;
		}	
	}
	protected void visit(Global nt) {

		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueGlobal:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<GLOBAL> -> globales <HEADER> fin-globales;");
			break;			
			}	
	}
	
	protected void visit(G1 nt) {

		switch (nt.getNroProduccion()) {
		
		case IAnalizadorSintactico.PROD_ENCABEZADO:
			nt.getErrorManager().debug( "Reconocer BloqueG1:");
			break;
		
		case IAnalizadorSintactico.PROD_PRIMERA:
			nt.getErrorManager().debug( "<G1> ->		BLOQUE EOF |;");
			break;			

		case IAnalizadorSintactico.PROD_SEGUNDA:
			nt.getErrorManager().debug( "<G1> ->		         EOF;");
			break;
		}
	}
}
